package com.github.niefy.modules.third.task;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.github.niefy.common.utils.HttpClientUtil;
import com.github.niefy.modules.third.dto.in.ThirdTemplateMsgIn_001;
import com.github.niefy.modules.third.dto.out.ThirdTemplateMsgOut_001;
import com.github.niefy.modules.third.entity.ThirdTemplateMsgDetail;
import com.github.niefy.modules.third.entity.ThirdTemplateMsgTaskLog;
import com.github.niefy.modules.third.entity.ThirdTemplateMsgUnread;
import com.github.niefy.modules.third.entity.ThirdUser;
import com.github.niefy.modules.third.enums.SpmApiidEnum;
import com.github.niefy.modules.third.enums.SecApiURLEnum;
import com.github.niefy.modules.third.enums.TemplateMsgPushFlagEnum;
import com.github.niefy.modules.third.enums.TemplateMsgReadFlagEnum;
import com.github.niefy.modules.third.service.*;
import com.github.niefy.modules.wx.service.TemplateMsgService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;

/**
 * @author : [86188]
 * @description : spm模板消息代发定时任务，触发器配置在QuartzConfig.java
 * @createTime : [2023/3/28 16:46]
 * @updateUser : [86188]
 * @updateTime : [2023/3/28 16:46]
 */
@Slf4j
public class TemplateMsgJob extends QuartzJobBean {

    @Value("${sec-api.spm.domain}")
    String spmDomain;
    @Value("${sec-api.spm.accesskey}")
    String accesskey;
    @Value("${sec-api.spm.wx-appid}")
    String appid;
    @Value("${sec-api.spm.templateid}")
    String templateid;


    private final ThirdTemplateMsgTaskLogService thirdTemplateMsgTaskLogService = SpringUtil.getBean(ThirdTemplateMsgTaskLogService.class);
    private final ThirdTemplateMsgDetailService thirdTemplateMsgDetailService = SpringUtil.getBean(ThirdTemplateMsgDetailService.class);
    private final ThirdTemplateMsgUnreadService thirdTemplateMsgUnreadService = SpringUtil.getBean(ThirdTemplateMsgUnreadService.class);
    private final TemplateMsgService templateMsgService = SpringUtil.getBean(TemplateMsgService.class);
    private final ThirdUserService thirdUserService = SpringUtil.getBean(ThirdUserService.class);

    @Override
    @Transactional
    public void executeInternal(JobExecutionContext context) throws JobExecutionException {
        String url = spmDomain + SecApiURLEnum.SPM_CALL;
        //region 构建请求参数,查询third_template_msg_task_log，有最大消息序列号记录则+1作为from
        //查询本地拉取记录没有则取零
        var maxSeqHist = thirdTemplateMsgTaskLogService.getMaxSeq();
        var seqFromReq = maxSeqHist + 1;
        var reqOut = ThirdTemplateMsgOut_001.builder()
                .msgpushseqidfrom(seqFromReq)
                .pushflag(TemplateMsgPushFlagEnum.ONE.getValue())
                .build();
        reqOut.createSign(SpmApiidEnum.queryspmstumsglist.name(),  "SPMSTU",
                "consid", accesskey, "SPMSTU");
        //endregion
        //region 发送批量拉取模板消息记录请求，记录third_template_msg_task_log
        ThirdTemplateMsgIn_001 thirdTemplateMsgIn_001 = HttpClientUtil.http2GetJsonSync(url, ThirdTemplateMsgIn_001.class, reqOut);
        var msglist = thirdTemplateMsgIn_001.getMsglist();
        //获取该次请求响应的最大消息序列号
        if (ObjectUtil.isEmpty(msglist)){
            log.info("拉取消息列表为空");
            return;
        }
        var respMaxSeq = msglist.stream()
                .max(Comparator.comparing(ThirdTemplateMsgIn_001.StuMsgInfo::getMsgpushseqid));
        var thirdTemplateMsgTaskLog = ThirdTemplateMsgTaskLog.builder().pullTime(LocalDateTime.now()).build();
        //有当次请求最大记录，记录实际序列号区间，无记录，记录原最大序列号，区间为0
        respMaxSeq.ifPresentOrElse((stuMsgInfo)->{thirdTemplateMsgTaskLog.setMsgPushSeqIdFrom(seqFromReq);
                    thirdTemplateMsgTaskLog.setMsgPushSeqIdTo(stuMsgInfo.getMsgpushseqid());},
                ()-> {thirdTemplateMsgTaskLog.setMsgPushSeqIdFrom(maxSeqHist);
                    thirdTemplateMsgTaskLog.setMsgPushSeqIdTo(maxSeqHist);});
        thirdTemplateMsgTaskLogService.save(thirdTemplateMsgTaskLog);
        //记录该次请求消息明细信息third_template_msg_detail
        var thirdTemplateMsgDetails = new LinkedList<ThirdTemplateMsgDetail>();
        msglist.forEach((stuMsgInfo)->{
            thirdTemplateMsgDetails.add(ThirdTemplateMsgDetail.builder()
                    .msgId(stuMsgInfo.getMsgid())
                    .msgTypeName(stuMsgInfo.getMsgtypename())
                    .msgTypeId(stuMsgInfo.getMsgtypeid())
                    .batchNo(stuMsgInfo.getBatchno())
                    .batchName(stuMsgInfo.getBatchname())
                    .studentNo(stuMsgInfo.getStudentno())
                    .msgTitle(stuMsgInfo.getMsgtitle())
                    .msgContent(stuMsgInfo.getMsgcontent())
                    .validFlag(stuMsgInfo.getValidflag())
                    .operateDate(Instant.ofEpochMilli(stuMsgInfo.getOperatedate()).atZone(ZoneOffset.ofHours(8)).toLocalDateTime())
                    .pushFlag(stuMsgInfo.getPushflag())
                    .msgPushSeqId(stuMsgInfo.getMsgpushseqid())
                    .msgPushDate(Instant.ofEpochMilli(stuMsgInfo.getMsgpushdate()).atZone(ZoneOffset.ofHours(8)).toLocalDateTime())
                    .msgPushDateStr(stuMsgInfo.getMsgpushdatestr())
                    .build());
        });
        thirdTemplateMsgDetailService.saveBatch(thirdTemplateMsgDetails);
        //endregion
        //处理构建消息，发送消息，同时记录未读消息表
        //构建不成功的同样记录,pushFlag置为3则为构建失败还未向微信服务器推送,已向微信服务器推送的消息为2
        thirdTemplateMsgDetails.forEach((thirdTemplateMsgDetail -> {
            ThirdUser thirdUser = thirdUserService.lambdaQuery()
                    .eq(ThirdUser::getThirdId, thirdTemplateMsgDetail.getStudentNo())
                    .one();
            thirdTemplateMsgDetail.setSendTime(LocalDateTime.now());

            if (thirdUser==null){
                thirdTemplateMsgDetail.setPushFlag(TemplateMsgPushFlagEnum.THREE.getValue());
                thirdTemplateMsgDetailService.updateById(thirdTemplateMsgDetail);
            }else {
                List<WxMpTemplateData> data  = new ArrayList<>();
                data.add(new WxMpTemplateData("keyword4",thirdTemplateMsgDetail.getMsgTitle()));
                WxMpTemplateMessage msg = WxMpTemplateMessage.builder()
                        .templateId(templateid)
                        .toUser(thirdUser.getOpenId())
                        .data(data)
                        .build();
                templateMsgService.sendTemplateMsg(msg, appid);
                thirdTemplateMsgDetail.setPushFlag(TemplateMsgPushFlagEnum.TWO.getValue());
                thirdTemplateMsgDetailService.updateById(thirdTemplateMsgDetail);
                //构建保存未读消息记录
                var templateMsgUnread = ThirdTemplateMsgUnread.builder()
                        .msgId(thirdTemplateMsgDetail.getMsgId())
                        .openId(thirdUser.getOpenId())
                        .thirdId(thirdUser.getThirdId())
                        .readFlag(TemplateMsgReadFlagEnum.UNREAD.getValue())
                        .build();
                thirdTemplateMsgUnreadService.save(templateMsgUnread);
            }
        }));
    }
}
